M13.3: jump-string parser + JumpHost type (FR-56, FR-57)#11
Merged
Conversation
Adds the public `proxy::jump` submodule: JumpHost (struct): - pub fields: host: String, port: u16, user: Option<String>, identity_files: Vec<PathBuf>. - The chain manager (M13.4) populates identity_files by re-running ssh_config::resolve against each hop's name; M13.3 leaves it empty. parse_jump_chain(raw: &str) -> Result<Vec<JumpHost>, AnvilError>: - Accepts the OpenSSH `-J` / `ProxyJump` syntax: `[user@]host[:port]` comma-separated, whitespace-around-commas tolerated. - Defaults the port to 22, leaves user as None when omitted. - Rejects empty strings, trailing/double commas, empty user prefix, empty host, invalid port, and the literal `none` (case-insensitive) with clear actionable error messages. MAX_JUMP_HOPS = 8: - Matches OpenSSH's READCONF_MAX_DEPTH for ProxyJump chains (FR-57). - Enforced at parse time, not chain-construction time, so callers bail out before any network I/O. IPv6 literals (`[::1]:22`) are not in scope for M13 — none of the listed FRs require them and the OpenSSH convention is rare in ProxyJump strings; documented as a follow-up. Tests: +16 unit tests (single-hop bare, single-hop user@host:port, two-hop chain, whitespace tolerance, empty-string/whitespace-only, trailing/double commas, empty user, empty host, invalid port, out-of-range port, none literal in three case variants, max-length chain accepted, length+1 chain rejected, struct PartialEq+Clone sanity). 189 lib tests green, 0 failures. Plan: M13.3 of let-us-plan-on-bright-cosmos.md. Stacked on M13.2 (PR #7).
This was referenced May 4, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds the public
proxy::jumpsubmodule with the[user@]host[:port]parser and theJumpHosttype. Re-opened on a clean rebase off main; previous PR #8 was auto-closed when its base branch (M13.2) was deleted by the squash-merge.New public surface
proxy::JumpHost { host, port, user, identity_files }proxy::parse_jump_chain(raw: &str) -> Result<Vec<JumpHost>, AnvilError>proxy::MAX_JUMP_HOPS(= 8, matches OpenSSHREADCONF_MAX_DEPTHper FR-57)Grammar
OpenSSH
-J/ProxyJumpsyntax:[user@]host[:port], comma-separated. Whitespace around commas is tolerated. The literalnone(case-insensitive) is rejected with a cleardisable sentinelerror — callers that recognize it as the FR-59 disable sentinel should detect it before calling.Tests (16 new)
Single-hop bare, single-hop user@host:port, two-hop chain, whitespace tolerance, empty/whitespace-only string, trailing/double commas, empty user, empty host, invalid port, port out of range,
noneliteral in three case variants, max-length chain accepted, length+1 rejected, structPartialEq+Clonesanity. Total: 185 lib tests, 0 failures.Out of scope
[::1]:22) — rare in ProxyJump strings, not exercised by the listed FRs.ssh_configresolution — happens at the chain manager (M13.4) / dispatcher (M13.6) layer.Test plan
cargo fmt/cargo clippy --all-targets -- -D warningsclean.cargo test --lib --tests --lockedgreen.Plan: M13.3 of let-us-plan-on-bright-cosmos.md.
🤖 Generated with Claude Code